C.S.Burner 🪙 ━►🔥GIT Node
Node / reticulum_mirror / MeshChatX / files / meshchatx / src / frontend / components / messages / ConversationPeerHeader.vue
Displaying Raw • Download
meshchatx/src/frontend/components/messages/ConversationPeerHeader.vue 65ca9ddc823fcc2c8f8653c553b944b85db0875f (65ca9ddc) Text, 14.72 KB
T8b949e<!-- SPDX-License-Identifier: 0BSD -->
Tff7b72<templateTff7b72>
Tff7b72<div
Te6edf3class=Ta5d6ff"Ta5d6ffrelative z-20 flex flex-wrap items-center gap-y-2 px-3 sm:px-4 py-3 border-b border-gray-200 dark:border-zinc-800 bg-white dark:bg-zinc-950Ta5d6ff"
Tff7b72>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffshrink-0 mr-3Ta5d6ff"Tff7b72>
Tff7b72<LxmfUserIcon
Te6edf3:custom-image=Ta5d6ff"Ta5d6ffselectedPeer.contact_imageTa5d6ff"
Te6edf3:icon-name=Ta5d6ff"Ta5d6ffselectedPeer.lxmf_user_icon ? selectedPeer.lxmf_user_icon.icon_name : Ta5d6ff'Ta5d6ff'Ta5d6ff"
Te6edf3:icon-foreground-colour=Ta5d6ff"
Ta5d6ff selectedPeer.lxmf_user_icon ? selectedPeer.lxmf_user_icon.foreground_colour : Ta5d6ff'Ta5d6ff'
Ta5d6ff Ta5d6ff"
Te6edf3:icon-background-colour=Ta5d6ff"
Ta5d6ff selectedPeer.lxmf_user_icon ? selectedPeer.lxmf_user_icon.background_colour : Ta5d6ff'Ta5d6ff'
Ta5d6ff Ta5d6ff"
Te6edf3icon-class=Ta5d6ff"Ta5d6ffshrink-0Ta5d6ff"
Te6edf3:icon-style=Ta5d6ff"Ta5d6ffmessageIconStyleTa5d6ff"
Tff7b72/>
Tff7b72</div>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffmin-w-0 flex-1Ta5d6ff"Tff7b72>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffflex items-center cursor-pointer min-w-0 groupTa5d6ff" @Te6edf3click=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffedit-display-nameTa5d6ff'Ta5d6ff)Ta5d6ff"Tff7b72>
Tff7b72<div
Te6edf3v-if=Ta5d6ff"Ta5d6ffselectedPeer.custom_display_name != nullTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffmr-1.5 text-gray-500 dark:text-zinc-400 group-hover:text-gray-700 dark:group-hover:text-zinc-200 transition-colorsTa5d6ff"
Te6edf3:title=Ta5d6ff"Te6edf3$tTa5d6ff(Ta5d6ff'Ta5d6ffmessages.custom_display_nameTa5d6ff'Ta5d6ff)Ta5d6ff"
Tff7b72>
Tff7b72<MaterialDesignIcon Te6edf3icon-name=Ta5d6ff"Ta5d6fftag-outlineTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffsize-4Ta5d6ff" Tff7b72/>
Tff7b72</div>
Tff7b72<div
Te6edf3class=Ta5d6ff"Ta5d6fffont-semibold text-gray-900 dark:text-zinc-100 truncate max-w-[min(40vw,12rem)] sm:max-w-sm text-baseTa5d6ff"
Te6edf3:title=Ta5d6ff"Ta5d6ffselectedPeer.custom_display_name ?? selectedPeer.display_nameTa5d6ff"
Tff7b72>
{{ selectedPeer.custom_display_name ?? selectedPeer.display_name }}
Tff7b72</div>
Tff7b72</div>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6fftext-xs text-gray-500 dark:text-zinc-400 mt-0.5 flex items-center gap-2 min-w-0Ta5d6ff"Tff7b72>
Tff7b72<div
Te6edf3class=Ta5d6ff"Ta5d6ffcursor-pointer hover:text-blue-500 transition-colors truncate max-w-[min(40vw,12rem)] sm:max-w-none shrink-0Ta5d6ff"
Te6edf3:title=Ta5d6ff"Ta5d6ffselectedPeer.destination_hashTa5d6ff"
@Te6edf3click=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffcopy-hashTa5d6ff'Ta5d6ff, selectedPeer.destination_hash)Ta5d6ff"
Tff7b72>
{{ destinationDisplay }}
Tff7b72</div>
Tff7b72<div
Te6edf3v-if=Ta5d6ff"
Ta5d6ff showPeerPathRow ||
selectedPeerSignalMetrics?.snr != null ||
selectedPeerLxmfStampInfo?.stamp_cost ||
lxmfHasOutboundTicket
Ta5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffflex items-center gap-2 min-w-0Ta5d6ff"
Tff7b72>
Tff7b72<span Te6edf3class=Ta5d6ff"Ta5d6fftext-gray-300 dark:text-zinc-700 shrink-0Ta5d6ff"Tff7b72>•Tff7b72</span>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffflex items-center gap-2 truncateTa5d6ff"Tff7b72>
Tff7b72<span
Te6edf3v-if=Ta5d6ff"Ta5d6ffshowPeerPathRowTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffflex items-center gap-1 shrink-0Ta5d6ff"
Te6edf3:class=Ta5d6ff"Ta5d6ffpeerPathRowClassTa5d6ff"
Te6edf3:title=Ta5d6ff"Ta5d6ffpeerPathRowTitleTa5d6ff"
@Te6edf3click=Ta5d6ff"Ta5d6ffonPeerPathRowClickTa5d6ff"
Tff7b72>
Tff7b72<MaterialDesignIcon
Te6edf3v-if=Ta5d6ff"Ta5d6ffpeerPathBusyTa5d6ff"
Te6edf3icon-name=Ta5d6ff"Ta5d6ffloadingTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffsize-3.5 animate-spin shrink-0Ta5d6ff"
Tff7b72/>
Tff7b72<spanTff7b72>{{ peerPathRowLabel }}Tff7b72</span>
Tff7b72</span>
Tff7b72<span Te6edf3v-if=Ta5d6ff"Ta5d6ffselectedPeerSignalMetrics?.snr != nullTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffflex items-center gap-2 shrink-0Ta5d6ff"Tff7b72>
Tff7b72<span Te6edf3class=Ta5d6ff"Ta5d6fftext-gray-300 dark:text-zinc-700 opacity-50Ta5d6ff"Tff7b72>•Tff7b72</span>
Tff7b72<span
Te6edf3class=Ta5d6ff"Ta5d6ffcursor-pointer hover:text-gray-700 dark:hover:text-zinc-200Ta5d6ff"
Te6edf3title=Ta5d6ff"Ta5d6ffSignal qualityTa5d6ff"
@Te6edf3click=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffsignal-metrics-clickTa5d6ff'Ta5d6ff, selectedPeerSignalMetrics)Ta5d6ff"
Tff7b72>{{ Te6edf3$t("messages.snr", { snr: selectedPeerSignalMetrics.snr }) }}Tff7b72</span
>
Tff7b72</span>
Tff7b72<span
Te6edf3v-if=Ta5d6ff"Ta5d6ffselectedPeerLxmfStampInfo?.stamp_cost || lxmfHasOutboundTicketTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffflex items-center gap-1 shrink-0Ta5d6ff"
Tff7b72>
Tff7b72<span Te6edf3class=Ta5d6ff"Ta5d6fftext-gray-300 dark:text-zinc-700 opacity-50Ta5d6ff"Tff7b72>•Tff7b72</span>
Tff7b72<MaterialDesignIcon
Te6edf3v-if=Ta5d6ff"Ta5d6fflxmfHasOutboundTicketTa5d6ff"
Te6edf3icon-name=Ta5d6ff"Ta5d6ffticket-confirmationTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffsize-3.5 shrink-0Ta5d6ff"
Te6edf3:class=Ta5d6ff"
Ta5d6ff lxmfStampTicketValid
? Ta5d6ff'Ta5d6fftext-emerald-600 dark:text-emerald-400Ta5d6ff'
Ta5d6ff : Ta5d6ff'Ta5d6fftext-amber-600 dark:text-amber-500Ta5d6ff'
Ta5d6ff Ta5d6ff"
Te6edf3:title=Ta5d6ff"
Ta5d6ff lxmfStampTicketValid
? Te6edf3$tTa5d6ff(Ta5d6ff'Ta5d6ffmessages.stamp_ticket_validTa5d6ff'Ta5d6ff, {
expires: lxmfStampTicketExpiresRelative,
})
: Te6edf3$tTa5d6ff(Ta5d6ff'Ta5d6ffmessages.stamp_ticket_expiredTa5d6ff'Ta5d6ff)
Ta5d6ff"
Tff7b72/>
Tff7b72<span
Te6edf3v-if=Ta5d6ff"Ta5d6ffselectedPeerLxmfStampInfo?.stamp_costTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6ffcursor-pointer hover:text-gray-700 dark:hover:text-zinc-200Ta5d6ff"
Te6edf3title=Ta5d6ff"Ta5d6ffLXMF stamp requirementTa5d6ff"
@Te6edf3click=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffstamp-info-clickTa5d6ff'Ta5d6ff, selectedPeerLxmfStampInfo)Ta5d6ff"
Tff7b72>{{ Te6edf3$t("messages.stamp_cost", { cost: selectedPeerLxmfStampInfo.stamp_cost }) }}Tff7b72</span
>
Tff7b72</span>
Tff7b72</div>
Tff7b72</div>
Tff7b72</div>
Tff7b72</div>
Tff7b72<div Te6edf3class=Ta5d6ff"Ta5d6ffml-auto flex items-center gap-0.5 sm:gap-1.5 min-w-0 shrink-0Ta5d6ff"Tff7b72>
Tff7b72<DropDownMenu Te6edf3v-if=Ta5d6ff"Ta5d6ff!compactPeerActionsTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffshrink-0Ta5d6ff" Te6edf3data-testid=Ta5d6ff"Ta5d6ffconversation-path-opsTa5d6ff"Tff7b72>
Tff7b72<template #buttonTff7b72>
Tff7b72<IconButton
Te6edf3:title=Ta5d6ff"Te6edf3$tTa5d6ff(Ta5d6ff'Ta5d6ffnomadnet.path_finderTa5d6ff'Ta5d6ff)Ta5d6ff"
Te6edf3:disabled=Ta5d6ff"Ta5d6ffpathfinderInProgressTa5d6ff"
Te6edf3class=Ta5d6ff"Ta5d6fftext-blue-600 dark:text-blue-400Ta5d6ff"
Tff7b72>
Tff7b72<MaterialDesignIcon
Te6edf3:icon-name=Ta5d6ff"Ta5d6ffpathfinderInProgress ? Ta5d6ff'Ta5d6ffloadingTa5d6ff'Ta5d6ff : Ta5d6ff'Ta5d6ffmap-marker-pathTa5d6ff'Ta5d6ff"
Te6edf3:class=Ta5d6ff"Ta5d6ff[Ta5d6ff'Ta5d6ffsize-6 sm:size-7Ta5d6ff'Ta5d6ff, pathfinderInProgress ? Ta5d6ff'Ta5d6ffanimate-spinTa5d6ff'Ta5d6ff : Ta5d6ff'Ta5d6ff'Ta5d6ff]Ta5d6ff"
Tff7b72/>
Tff7b72</IconButton>
Tff7b72</template>
Tff7b72<template #itemsTff7b72>
Tff7b72<DropDownMenuItem @Te6edf3click=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffpath-finder-quickTa5d6ff'Ta5d6ff)Ta5d6ff"Tff7b72>
Tff7b72<MaterialDesignIcon Te6edf3icon-name=Ta5d6ff"Ta5d6ffflashTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffsize-5Ta5d6ff" Tff7b72/>
Tff7b72<spanTff7b72>{{ Te6edf3$t("nomadnet.path_finder_quick_request") }}Tff7b72</span>
Tff7b72</DropDownMenuItem>
Tff7b72<DropDownMenuItem @Te6edf3click=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffpath-finder-forceTa5d6ff'Ta5d6ff)Ta5d6ff"Tff7b72>
Tff7b72<MaterialDesignIcon Te6edf3icon-name=Ta5d6ff"Ta5d6ffmap-marker-radiusTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffsize-5Ta5d6ff" Tff7b72/>
Tff7b72<spanTff7b72>{{ Te6edf3$t("nomadnet.path_finder_force_find") }}Tff7b72</span>
Tff7b72</DropDownMenuItem>
Tff7b72<DropDownMenuItem @Te6edf3click=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffpath-finder-dropTa5d6ff'Ta5d6ff)Ta5d6ff"Tff7b72>
Tff7b72<MaterialDesignIcon Te6edf3icon-name=Ta5d6ff"Ta5d6ffreload-alertTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffsize-5Ta5d6ff" Tff7b72/>
Tff7b72<spanTff7b72>{{ Te6edf3$t("nomadnet.path_finder_drop_and_request") }}Tff7b72</span>
Tff7b72</DropDownMenuItem>
Tff7b72</template>
Tff7b72</DropDownMenu>
Tff7b72<ConversationDropDownMenu
Te6edf3v-if=Ta5d6ff"Ta5d6ffselectedPeerTa5d6ff"
Te6edf3:peer=Ta5d6ff"Ta5d6ffselectedPeerTa5d6ff"
Te6edf3:compact=Ta5d6ff"Ta5d6ffcompactPeerActionsTa5d6ff"
Te6edf3:has-failed-messages=Ta5d6ff"Ta5d6ffhasFailedOrCancelledMessagesTa5d6ff"
Te6edf3:pathfinder-in-progress=Ta5d6ff"Ta5d6ffpathfinderInProgressTa5d6ff"
@Te6edf3conversation-deleted=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffconversation-deletedTa5d6ff'Ta5d6ff)Ta5d6ff"
@Te6edf3set-custom-display-name=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffedit-display-nameTa5d6ff'Ta5d6ff)Ta5d6ff"
@Te6edf3popout=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffpopoutTa5d6ff'Ta5d6ff)Ta5d6ff"
@Te6edf3retry-failed=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffretry-failedTa5d6ff'Ta5d6ff)Ta5d6ff"
@Te6edf3open-telemetry-history=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffopen-telemetry-historyTa5d6ff'Ta5d6ff)Ta5d6ff"
@Te6edf3start-call=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffstart-callTa5d6ff'Ta5d6ff)Ta5d6ff"
@Te6edf3share-contact=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffshare-contactTa5d6ff'Ta5d6ff)Ta5d6ff"
@Te6edf3path-finder-quick=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffpath-finder-quickTa5d6ff'Ta5d6ff)Ta5d6ff"
@Te6edf3path-finder-force=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffpath-finder-forceTa5d6ff'Ta5d6ff)Ta5d6ff"
@Te6edf3path-finder-drop=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffpath-finder-dropTa5d6ff'Ta5d6ff)Ta5d6ff"
Tff7b72/>
Tff7b72<IconButton Te6edf3title=Ta5d6ff"Ta5d6ffCloseTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffshrink-0Ta5d6ff" @Te6edf3click=Ta5d6ff"Te6edf3$emitTa5d6ff(Ta5d6ff'Ta5d6ffcloseTa5d6ff'Ta5d6ff)Ta5d6ff"Tff7b72>
Tff7b72<MaterialDesignIcon Te6edf3icon-name=Ta5d6ff"Ta5d6ffcloseTa5d6ff" Te6edf3class=Ta5d6ff"Ta5d6ffsize-6 sm:size-7Ta5d6ff" Tff7b72/>
Tff7b72</IconButton>
Tff7b72</div>
Tff7b72</div>
Tff7b72</template>
Tff7b72<scriptTff7b72>
import Utils from "../../js/Utils";
import { fromNow } from "../../libs/datetime.js";
import MaterialDesignIcon from "../MaterialDesignIcon.vue";
import IconButton from "../IconButton.vue";
import LxmfUserIcon from "../LxmfUserIcon.vue";
import ConversationDropDownMenu from "./ConversationDropDownMenu.vue";
import DropDownMenu from "../DropDownMenu.vue";
import DropDownMenuItem from "../DropDownMenuItem.vue";
export default {
name: "ConversationPeerHeader",
components: {
MaterialDesignIcon,
IconButton,
LxmfUserIcon,
ConversationDropDownMenu,
DropDownMenu,
DropDownMenuItem,
},
props: {
selectedPeer: {
type: Object,
required: true,
},
compactPeerActions: {
type: Boolean,
default: false,
},
hasFailedOrCancelledMessages: {
type: Boolean,
default: false,
},
messageIconStyle: {
type: Object,
default: () => ({}),
},
selectedPeerPath: {
type: Object,
default: null,
},
peerPathSnapshot: {
type: Object,
default: null,
},
peerPathLoading: {
type: Boolean,
default: false,
},
peerPathWarming: {
type: Boolean,
default: false,
},
selectedPeerSignalMetrics: {
type: Object,
default: null,
},
selectedPeerLxmfStampInfo: {
type: Object,
default: null,
},
pathfinderInProgress: {
type: Boolean,
default: false,
},
},
emits: [
"edit-display-name",
"copy-hash",
"destination-path-click",
"signal-metrics-click",
"stamp-info-click",
"conversation-deleted",
"popout",
"retry-failed",
"open-telemetry-history",
"start-call",
"share-contact",
"close",
"path-finder-quick",
"path-finder-force",
"path-finder-drop",
],
computed: {
destinationDisplay() {
return Utils.formatDestinationHash(this.selectedPeer?.destination_hash);
},
peerPathBusy() {
return this.pathfinderInProgress || this.peerPathWarming;
},
showPeerPathRow() {
return (
this.peerPathBusy ||
this.peerPathLoading ||
this.selectedPeerPath != null ||
(this.peerPathSnapshot != null && !this.selectedPeerPath)
);
},
peerPathRowLabel() {
if (this.peerPathBusy) {
return this.$t("messages.outbound_pathfinding_short");
}
if (this.peerPathLoading && !this.selectedPeerPath) {
return this.$t("messages.path_loading");
}
if (this.selectedPeerPath) {
let label =
this.selectedPeerPath.hops === 0 || this.selectedPeerPath.hops === 1
? this.$t("messages.direct")
: this.$t("messages.hops_away", { count: this.selectedPeerPath.hops });
if (this.peerPathSnapshot?.path_stale) {
label += ` (${this.$t("messages.path_stale_label")})`;
} else if (this.peerPathSnapshot?.path_unresponsive) {
label += ` (${this.$t("messages.path_unresponsive_label")})`;
}
return label;
}
return this.$t("messages.path_no_route");
},
peerPathRowClass() {
const base = "cursor-pointer hover:text-gray-700 dark:hover:text-zinc-200";
if (this.peerPathBusy) {
return `${base} text-blue-600 dark:text-blue-400`;
}
if (!this.selectedPeerPath) {
return `${base} text-amber-700 dark:text-amber-400`;
}
if (this.peerPathSnapshot?.path_stale || this.peerPathSnapshot?.path_unresponsive) {
return `${base} text-amber-700 dark:text-amber-400`;
}
return base;
},
peerPathRowTitle() {
if (this.peerPathBusy) {
return this.$t("messages.outbound_pathfinding_tooltip");
}
if (!this.selectedPeerPath) {
return this.$t("messages.path_no_route_hint");
}
return this.$t("messages.path_info_title");
},
lxmfHasOutboundTicket() {
return this.selectedPeerLxmfStampInfo?.outbound_ticket_expiry != null;
},
lxmfStampTicketExpiryMs() {
const e = this.selectedPeerLxmfStampInfo?.outbound_ticket_expiry;
if (e == null) {
return null;
}
const n = Number(e);
if (!Number.isFinite(n)) {
return null;
}
return n * 1000;
},
lxmfStampTicketValid() {
const ms = this.lxmfStampTicketExpiryMs;
if (ms == null) {
return false;
}
return ms > Date.now();
},
lxmfStampTicketExpiresRelative() {
const ms = this.lxmfStampTicketExpiryMs;
if (ms == null) {
return "";
}
return fromNow(ms);
},
},
methods: {
onPeerPathRowClick() {
if (this.selectedPeerPath) {
this.$emit("destination-path-click", this.selectedPeerPath);
}
},
},
};
Tff7b72</script>
Served by rngit 1.5.2 - Generated in 0.05s